#!/usr/bin/env python
# -*- coding: utf8 -*-
# title       :
# description :
# author      :'ShenMeng'

from PySide import QtCore, QtGui

class GrabRect(QtGui.QFrame):
    def __init__(self, parent=None):
        super(GrabRect, self).__init__(parent)

        self.start_pos = None
        self.end_pos = None
        self._parent = parent
        self._padding = 5
        self.SHADOW_WIDTH=0   #边框距
        self.isLeftPressDown = False #鼠标左键是否按下
        self.dragPosition=0     #拖动时坐标
        self.Numbers = self.enum(UP=0, DOWN=1, LEFT=2, RIGHT=3, LEFTTOP=4, LEFTBOTTOM=5, RIGHTBOTTOM=6, RIGHTTOP=7, NONE=8) #枚举参数

        self.dir=self.Numbers.NONE #初始鼠标状态

        self.setMouseTracking(True)

    # 枚举参数
    def enum(self, **enums):
        return type('Enum', (), enums)

    def region(self,cursorGlobalPoint):
        # 获取窗体在屏幕上的位置区域，tl为topleft点，rb为rightbottom点
        rect = self.rect()
        tl = self.mapToGlobal(rect.topLeft())
        rb = self.mapToGlobal(rect.bottomRight())
        x = cursorGlobalPoint.x()
        y = cursorGlobalPoint.y()
        if(tl.x() + self._padding >= x and tl.x() <= x and tl.y() + self._padding >= y and tl.y() <= y):
            #左上角
            self.dir = self.Numbers.LEFTTOP
            # 设置鼠标形状
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeFDiagCursor))
        elif(x >= rb.x() - self._padding and x <= rb.x() and y >= rb.y() - self._padding and y <= rb.y()):
            #右下角
            self.dir = self.Numbers.RIGHTBOTTOM
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeFDiagCursor))
        elif(x <= tl.x() + self._padding and x >= tl.x() and y >= rb.y() - self._padding and y <= rb.y()):
            # 左下角
            self.dir = self.Numbers.LEFTBOTTOM
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeBDiagCursor))
        elif(x <= rb.x() and x >= rb.x() - self._padding and y >= tl.y() and y <= tl.y() + self._padding):
            #右上角
            self.dir = self.Numbers.RIGHTTOP
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeBDiagCursor))
        elif(x <= tl.x() + self._padding and x >= tl.x()):
            #左边
            self.dir = self.Numbers.LEFT
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeHorCursor))
        elif( x <= rb.x() and x >= rb.x() - self._padding):
            #右边
            self.dir = self.Numbers.RIGHT
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeHorCursor))
        elif(y >= tl.y() and y <= tl.y() + self._padding):
            #上边
            self.dir = self.Numbers.UP
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeVerCursor))
        elif(y <= rb.y() and y >= rb.y() - self._padding):
            #下边
            self.dir = self.Numbers.DOWN
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeVerCursor))
        else:
            #默认
            self.dir = self.Numbers.NONE
            self.setCursor(QtGui.QCursor(QtCore.Qt.SizeAllCursor))
            #self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    def mouseReleaseEvent(self,event):
        self.isLeftPressDown = False
        if(event.button() == QtCore.Qt.LeftButton):
            self.end_pos = event.globalPos()
            self._parent._draw = None
        if(self.dir != self.Numbers.NONE):
            self.releaseMouse()
            self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    def mousePressEvent(self,event):
        if(event.button()==QtCore.Qt.LeftButton):
            self._parent._draw = True
            self.isLeftPressDown=True
            self.start_pos = event.globalPos()
            self.top_left = self.mapToGlobal(self.rect().topLeft())
            self.bottom_right = self.mapToGlobal(self.rect().bottomRight())
            self.parent_bottom_right = self._parent.mapToGlobal(self._parent.rect().bottomRight())

        if(self.dir != self.Numbers.NONE):
            self.mouseGrabber()
        else:
            self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()

    def mouseMoveEvent(self,event):
        self.end_pos = event.globalPos()
        gloPoint = event.globalPos()
        rect = self.rect()
        tl = self.mapToGlobal(rect.topLeft())
        rb = self.mapToGlobal(rect.bottomRight())

        if(not self.isLeftPressDown):
            self.region(gloPoint)
        else:
            if(self.dir != self.Numbers.NONE):
                rmove = QtCore.QRect(tl, rb)
                if(self.dir==self.Numbers.LEFT):
                    if(rb.x() - gloPoint.x() <= self.minimumWidth()):
                        rmove.setX(tl.x())
                    else:
                        rmove.setX(gloPoint.x())
                elif(self.dir==self.Numbers.RIGHT):
                    rmove.setWidth(gloPoint.x() - tl.x())
                elif(self.dir==self.Numbers.UP):
                    if(rb.y() - gloPoint.y() <= self.minimumHeight()):
                        rmove.setY(tl.y())
                    else:
                        rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.DOWN):
                    rmove.setHeight(gloPoint.y() - tl.y())
                elif(self.dir==self.Numbers.LEFTTOP):
                    if(rb.x() - gloPoint.x() <= self.minimumWidth()):
                        rmove.setX(tl.x())
                    else:
                        rmove.setX(gloPoint.x())
                    if(rb.y() - gloPoint.y() <= self.minimumHeight()):
                        rmove.setY(tl.y())
                    else:
                        rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.RIGHTTOP):
                    rmove.setWidth(gloPoint.x() - tl.x())
                    rmove.setY(gloPoint.y())
                elif(self.dir==self.Numbers.LEFTBOTTOM):
                    rmove.setX(gloPoint.x())
                    rmove.setHeight(gloPoint.y() - tl.y())
                elif(self.dir==self.Numbers.RIGHTBOTTOM):
                    rmove.setWidth(gloPoint.x() - tl.x())
                    rmove.setHeight(gloPoint.y() - tl.y())
                else:
                    pass
                self.setGeometry(rmove)
            else:
                if not self.isLeftPressDown:
                    return
                min_x = self.start_pos.x() - self.top_left.x()
                max_x = self.parent_bottom_right.x()-self.bottom_right.x()+self.start_pos.x()
                min_y = self.start_pos.y() - self.top_left.y()
                max_y = self.parent_bottom_right.y()-self.bottom_right.y()+self.start_pos.y()
                if  min_x<= event.globalPos().x() <= max_x and min_y<= event.globalPos().y()<= max_y:

                    self.move(event.globalPos() - self.dragPosition)
                else:
                    if min_x > event.globalPos().x() and min_y > event.globalPos().y():
                        pos = QtCore.QPoint(min_x, min_y)
                    elif min_x > event.globalPos().x() and min_y <= event.globalPos().y() <= max_y:
                        pos = QtCore.QPoint(min_x, event.globalPos().y())
                    elif min_x > event.globalPos().x() and event.globalPos().y() > max_y:
                        pos = QtCore.QPoint(min_x, max_y)
                    elif min_x <= event.globalPos().x() <= max_x and min_y > event.globalPos().y():
                        pos = QtCore.QPoint(event.globalPos().x(), min_y)
                    elif min_x <= event.globalPos().x() <= max_x and event.globalPos().y() > max_y:
                        pos = QtCore.QPoint(event.globalPos().x(), max_y)
                    elif event.globalPos().x() > max_x and min_y > event.globalPos().y():
                        pos = QtCore.QPoint(max_x, min_y)
                    elif event.globalPos().x() > max_x and min_y <= event.globalPos().y() <=max_y:
                        pos = QtCore.QPoint(max_x, event.globalPos().y())
                    elif event.globalPos().x() > max_x and event.globalPos().y() > max_y:
                        pos = QtCore.QPoint(max_x, max_y)
                    else:
                        return
                    self.move(pos - self.dragPosition)

            event.accept()
            self._parent._draw = True
            self._parent.start_pos = self.mapToGlobal(self.rect().topLeft())
            self._parent.end_pos = self.mapToGlobal(self.rect().bottomRight())
            self._parent._capture_rect = QtCore.QRect(self.mapToGlobal(self.rect().topLeft()),
                                                      self.mapToGlobal(self.rect().bottomRight())).normalized()

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseMove:
            if event.buttons() == QtCore.Qt.NoButton:
                gloPoint = event.globalPos()
                self.region(gloPoint)
            else:
                pass  # do other stuff
        return super(GrabRect, self).eventFilter(source, event)

    def paintEvent(self, event):
        start_pos = event.rect().topLeft()
        end_pos = event.rect().bottomRight()
        painter = QtGui.QPainter(self)

        # Draw background. Aside from aesthetics, this makes the full
        # tool region accept mouse events.
        pen = QtGui.QPen(QtGui.QColor(0, 170, 230, 255), 1, QtCore.Qt.SolidLine)
        painter.setPen(pen)
        painter.setBrush(QtGui.QColor(0, 170, 230, 255))#QtGui.QColor(0, 0, 0, self._opacity))
        painter.drawLine(event.rect().left(), start_pos.y(),
                         event.rect().right(), start_pos.y())

        painter.drawLine(start_pos.x(), event.rect().top(),
                         start_pos.x(), event.rect().bottom())

        # Draw cropping markers at current mouse position
        painter.drawLine(event.rect().left(), end_pos.y(),
                         event.rect().right(), end_pos.y())
        painter.drawLine(end_pos.x(), event.rect().top(),
                         end_pos.x(), event.rect().bottom())

        ###
        pen = QtGui.QPen(QtGui.QColor(0, 170, 230, 255))
        pen.setWidth(8)
        painter.setPen(pen)
        # painter.drawRect(QtCore.QRect(click_pos, self._click_pos.x()+5, self._click_pos.y()+5))
        painter.drawPoint(start_pos.x(), start_pos.y())
        painter.drawPoint(start_pos.x(), end_pos.y())
        painter.drawPoint(end_pos.x(), start_pos.y())
        painter.drawPoint(end_pos.x(), end_pos.y())
        #  mid
        painter.drawPoint(start_pos.x(), (start_pos.y() +end_pos.y()) / 2.0)
        painter.drawPoint(end_pos.x(), (start_pos.y() + end_pos.y()) / 2.0)
        painter.drawPoint((start_pos.x() + end_pos.x()) / 2.0, start_pos.y())
        painter.drawPoint((start_pos.x() + end_pos.x()) / 2.0, end_pos.y())
